package com.example.maruko_course_backend.utils;

import com.example.maruko_course_backend.utils.dtos.CellObject;
import com.example.maruko_course_backend.utils.dtos.ExcelCell;
import com.example.maruko_course_backend.utils.dtos.ExcelWorkbook;
import com.example.maruko_course_backend.utils.dtos.RowObject;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class ExcelUtil {

  public static String getCellValue(ExcelWorkbook excelWorkbook, int x, int y) {
    List<ExcelCell> cells = getCells(excelWorkbook);
    for (ExcelCell cell : cells) {
      if (cell.getX() == x && cell.getY() == y) {
        return cell.getValue();
      }
    }
    return null;
  }

  public static String getCellHeader(ExcelWorkbook excelWorkbook, int headerIndex) {
    List<ExcelCell> cells = getCells(excelWorkbook);
    for (ExcelCell cell : cells) {
      if (cell.getX() == 1 && cell.getY() == headerIndex) {
        return cell.getValue();
      }
    }
    return null;
  }

  private static List<ExcelCell> getCells(ExcelWorkbook excelWorkbook) {
    return excelWorkbook.getSheet().getCells();
  }

  public static String getCellValueByHeader(ExcelWorkbook givenExcel, String headerName, int cellSeq) {
    List<ExcelCell> cells = getCells(givenExcel);
    int headerY = -1;
    for (ExcelCell cell : cells) {
      if (cell.getValue().equals(headerName)) {
        headerY = cell.getY();
      }
    }
    for (ExcelCell cell : cells) {
      if (cell.getY() == headerY && !cell.getValue().equals(headerName) && cell.getX() == (cellSeq + 1)) {
        return cell.getValue();
      }
    }
    return null;
  }

  public static CellObject getOneCellObject(ExcelWorkbook givenExcel, int headerSeq, int cellSeq) {
    String headerName = getCellHeader(givenExcel, headerSeq);
    String cellValueByHeader = getCellValueByHeader(givenExcel, headerName, cellSeq);
    CellObject cellObject = new CellObject();
    cellObject.setKey(headerName);
    cellObject.setValue(cellValueByHeader);
    return cellObject;
  }

  public static RowObject getOneRowObject(ExcelWorkbook givenExcel, int rowSeq) {
    RowObject rowObject = new RowObject();
    List<CellObject> cellObjects = new ArrayList<>();
    List<String> headers = getCellHeaders(givenExcel);
    for (int i = 1; i <= headers.size(); i++) {
      cellObjects.add(getOneCellObject(givenExcel, i, rowSeq));
    }
    rowObject.setCellObjects(cellObjects);
    return rowObject;
  }

  public static List<String> getCellHeaders(ExcelWorkbook givenExcel) {
    List<String> headers = new ArrayList<>();
    int maxColumnCount = getMaxColumnCount(givenExcel);
    for (int i = 1; i <= maxColumnCount; i++) {
      headers.add(getCellHeader(givenExcel, i));
    }
    return headers;
  }

  private static int getMaxColumnCount(ExcelWorkbook givenExcel) {
    int maxColumnCount = 0;
    List<ExcelCell> cells = getCells(givenExcel);
    List<Integer> allYs = cells.stream().map(ExcelCell::getY).collect(Collectors.toList());
    for (Integer y : allYs) {
      if (y > maxColumnCount) {
        maxColumnCount = y;
      }
    }
    return maxColumnCount;
  }

  public static List<RowObject> getRowObjects(ExcelWorkbook givenExcel) {
    List<RowObject> rowObjects = new ArrayList<>();
    int maxRowCount = getMaxRowCount(givenExcel);
    for (int i = 1; i <= maxRowCount; i++) {
      rowObjects.add(getOneRowObject(givenExcel, i));
    }
    return rowObjects;
  }

  private static int getMaxRowCount(ExcelWorkbook givenExcel) {
    int maxRowCount = -1;
    List<ExcelCell> cells = getCells(givenExcel);
    for (ExcelCell cell : cells) {
      if (cell.getX() > maxRowCount) {
        maxRowCount = cell.getX();
      }
    }
    return maxRowCount == -1 ? -1 : maxRowCount - 1;
  }
}
